
extern crate rand;

pub trait LevelGenerator {
    fn next_level(&mut self) -> usize ;
}



use rand::Rng;
pub struct RandomLevelGenerator {
    rng: rand::rngs::ThreadRng,
    max: usize,
    branch: usize,
}
impl RandomLevelGenerator {
    //max: 0-based, branch -> p=(1/branch)
    pub fn new(max: usize, branch: usize) -> Self {
        Self {
            rng: rand::thread_rng(),
            max,
            branch,
        }
    }
}
impl LevelGenerator for RandomLevelGenerator {
    fn next_level(&mut self) -> usize {
        let mut height = 1_usize;
        while height < self.max  
            && (self.rng.gen_range(0..self.branch) % self.branch == 0) {
            height += 1;
        }
        assert!(height >=1 && height <= self.max);
        height - 1
    }
}






pub struct MockLevelGenerator {
    max: usize,
    seqs: Vec<usize>,
    cur: usize,
}

impl MockLevelGenerator {
    //max-level: 0-based
    pub fn new(max: usize, seqs: Vec<usize>) -> Self {
        MockLevelGenerator{ 
            max,
            seqs,
            cur: 0,
        }
    }
}
impl LevelGenerator for MockLevelGenerator {
    fn next_level(&mut self) -> usize {
        let ret = self.seqs[self.cur];
        // cur + 1  >= seqs.size() ? 0 : cur + 1
        self.cur = if self.cur + 1 >= self.seqs.len() { 0 } else{ self.cur + 1 };
        // ret > max ? max : ret
        if ret > self.max { self.max } else{ ret }
    }
}



#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn random_test(){
        let max_level = 5;
        let branch = 2;
        let mut gen: Box<dyn LevelGenerator> = Box::new(RandomLevelGenerator::new(max_level, branch));
        println!("next_level is :{}", gen.next_level());
    }

    #[test]
    fn mock_test(){
        let mut gen: Box<dyn LevelGenerator> = Box::new(MockLevelGenerator::new(4, vec![0, 1, 2, 3, 4, 5, 6]));
        assert_eq!(0, gen.next_level());
        assert_eq!(1, gen.next_level());
        assert_eq!(2, gen.next_level());
        assert_eq!(3, gen.next_level());
        assert_eq!(4, gen.next_level());
        assert_eq!(4, gen.next_level());
        assert_eq!(4, gen.next_level());

        assert_eq!(0, gen.next_level());
        assert_eq!(1, gen.next_level());
        assert_eq!(2, gen.next_level());
        assert_eq!(3, gen.next_level());
        assert_eq!(4, gen.next_level());
        assert_eq!(4, gen.next_level());
        assert_eq!(4, gen.next_level());
    }

    #[test]
    fn use_random(){
        let mut rnd = rand::thread_rng().gen_range(1..4);
        assert!(rnd >=1 && rnd <= 4);
        println!("{rnd}");

        rnd = rand::thread_rng().gen_range(1..4);
        assert!(rnd >=1 && rnd <= 4);
        println!("{rnd}");

        rnd = rand::thread_rng().gen_range(1..4);
        println!("{rnd}");
        assert!(rnd >=1 && rnd <= 4);

        rnd = rand::thread_rng().gen_range(1..4);
        println!("{rnd}");
        assert!(rnd >=1 && rnd <= 4);
    }
}
